/**
 *  @file  TcpConnector.h version 1.0 2007-11-20
 *  @brief Define wrapper class TcpConnector for connecting socket.
 *  Copyright (c) 2007 by @author Zhao Jun <abitfree@gmail.com>
 */

#ifndef __TCP_CONNECTOR_H__
#define __TCP_CONNECTOR_H__

#include "TcpStream.h"
#include "InternetAddress.h"

namespace vs {
namespace net {

/**
@brief Wrapper class for connecting socket.
This class is a factory, and connect peer host, and establish new socket streams.
*/
class TcpConnector
{
public:
	///@{
	/// Establish new socket stream with peer host.
	template<typename SOCK>
	static bool Connect(InternetAddress &address, TemplateTcpStream<SOCK> &new_stream);
	template<typename SOCK>
	static bool Connect(const char *address, unsigned short port, TemplateTcpStream<SOCK> &new_stream);
	///@}

private:
	// Disable instancing this class.
	TcpConnector();

	// Disable deleting this class.
	~TcpConnector();
};

template<typename SOCK>
INLINE
bool TcpConnector::Connect(InternetAddress &address, TemplateTcpStream<SOCK> &new_stream)
{
	if (!new_stream.Create())
	{
		return false;
	}

	if (connect(new_stream.GetHandle(), (struct sockaddr*)address.GetAddress(), address.GetAddressSize()) == SOCKET_ERROR)
	{
#ifdef WIN32
		int error = WSAGetLastError();
		if (error == WSAEWOULDBLOCK)  // non-blocking, need call select later
		{
		}
#else
		if (errno == ETIMEDOUT)
		{
		}
		else if (errno == EINPROGRESS) // asyn socket, need call select later
		{
		}
#endif
		net_debug("TcpConnector::Connect() connect falied, error:%d\n", GetNetError());
		return false;
	}
	else
	{
		return true;
	}
}

template<typename SOCK>
INLINE
bool TcpConnector::Connect(const char *address, unsigned short port, TemplateTcpStream<SOCK> &new_stream)
{
	InternetAddress internet_address(port, address);
	return Connect(internet_address, new_stream);
}

}	// namespace net
}	// namespace vs

#endif	// __TCP_CONNECTOR_H__
